home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / Z80ppc 160.sit / Z80ppc 160 / Init_Z80.c < prev    next >
Text File  |  1995-11-19  |  11KB  |  360 lines

  1. /*    Z80 Emulator
  2.     Copyright (C) 1994 G.Woigk
  3.     
  4.     This file is part of Mac Spectacle and it is free software
  5.     See application.c for details
  6.             
  7.     This program is distributed in the hope that it will be useful,
  8.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  10.  
  11.     16.Jan.95     Fixed wrong calculation of parity flag        KIO !
  12.     28.Jan.95     CMD_PROFILE                            KIO !
  13.     29.Mrz.95     Separated this file from Z80.c                KIO !
  14.     01.Nov.95     Started work on paged memory model again    KIO !
  15. */
  16.  
  17. #include    "kio.h"
  18. #include    "z80.options"
  19. #include    "z80.h"
  20. #include    "application.h"
  21. #include    "quick_strings.h"
  22. #include    "z80 main.h"
  23. #include    "display.h"
  24.  
  25.  
  26. #define    maxrampages    8        // 128k RAM in 8 pages ˆ 16k
  27. #define    maxrompages    5        // the plus3 has 4 roms + if1 rom
  28. #define    pagesize        0x4000    // 16 kByte
  29. #define    pagemask        0x3FFF    // 16k-1
  30. #define    pagebits        14        // 14 bit address inside page
  31.  
  32.  
  33. int        z80_hardware    = zx_48k;    // actually emulated hardware ( as set up by Init_Z80() )
  34.  
  35.  
  36. #if CMD_PROFILE
  37.  
  38.     Boolean    count_instr    = false;
  39.  
  40.     long    *cnt_xx = nil;        // array: count use of normal instructions
  41.     long    *cnt_cb = nil;        // array: count use of CB instructions
  42.     long    *cnt_ed = nil;        // array: count use of ED instructions
  43.     long    *cnt_xy = nil;        // array: count use of ix and iy instructions
  44.     long    *cnt_xycb = nil;    // array: count use of ix/CB and iy/CB instructions
  45.  
  46. #endif
  47.  
  48.  
  49. #if PC_PROFILE
  50.  
  51.     Boolean    count_pc = false;
  52.  
  53.     long    *cnt_pc    = nil;        // array: count instruction executions per location in RAM
  54.  
  55. #endif
  56.  
  57.  
  58. // -----    The Z80 core --------------------------------------------------------------
  59. Char**    CORE_M        = nil;    // master handle for all allocated RAM and ROM
  60. Char*    CORE         = nil;    // do not use any longer!!!
  61. Char*    rpage[4];                // mapped in pages for reading
  62. Char*    wpage[4];                // mapped in pages for writing
  63. Char*    ram[maxrampages];        // real RAM pages
  64. Char*    rom[maxrompages];        // real ROM pages
  65. Char*    norom        = nil;    // dummy page for writing to ROM
  66.  
  67. Char        zx128pagectrl    = 0;        // last byte sent to ZX 128's paging control port
  68.  
  69.  
  70. // -----    The Z80 registers --------------------------------------------------
  71. z80        zreg;                // contains z80 registers on entry/return of Z80()
  72.  
  73.  
  74. // -----    Flags after logic operations -------------------------------------
  75. Char        zlog_flags[256];        // convert:   A -> Z80-flags with V=parity, S, Z, and C=0
  76. #if !GENERATINGPOWERPC
  77. Char        mlog_flags[256];        // convert:   A-register  ->  68000 flags with V=parity and C=0
  78. Char        z80flags[256];            // convert:   68000 flagbyte  ->  Z80 flagbyte
  79. Char        m68flags[256];        // convert:   Z80 flagbyte  ->  68000 flagbyte
  80. #endif
  81.  
  82.  
  83. // =====    Utilities ========================================================
  84.  
  85.  
  86. // -----    Peek, Poke and calculate EA for peeking and poking -----------------------------
  87. //        These are inappropriate for macros, because the address is used twice
  88. //        note:    rpage[] and wpage[] pointers are calculated that way, that the unmasked address 
  89. //            must be added to address the right byte in the Macintosh's RAM !
  90.  
  91. Char*  RdPtr    ( Short addr )    {  return  rpage[addr>>pagebits] + addr;     }    // ptr for reading
  92. Char*  WrPtr    ( Short addr )    {  return wpage[addr>>pagebits] + addr;     }    // ptr for writing
  93.  
  94. Char    Peek    ( Short addr )            {  return  rpage[addr>>pagebits][addr];          }
  95.        Poke    ( Short addr, Char byte )    {             wpage[addr>>pagebits][addr] = byte;    }
  96.  
  97.  
  98. // -----    Write from/to core, buffer and file -------------------------------------------
  99. //        file operations return 0 if ok else OS error
  100.  
  101. long        tfu;                // after read/write to file: bytes actually transferred
  102.  
  103.  
  104. /* -----    Write buffer to file ----------------------------------------------------------
  105. */
  106. OSErr Buffer2File ( void* bu, short fileID, long len )
  107. {    
  108.     tfu = len;
  109.     return FSWrite ( fileID, &tfu, bu );
  110. }
  111.  
  112.  
  113. /* -----    Read buffer from file --------------------------------------------------------
  114. */
  115. OSErr File2Buffer ( short fileID, void* bu, long len )
  116. {
  117.     tfu = len;  
  118.     return FSRead ( fileID, &tfu, bu );
  119. }
  120.  
  121.  
  122. /* -----    Write core to file ------------------------------------------------------------
  123.         saves what the z80 cpu would read
  124. */
  125. OSErr Core2File ( Short addr, short fileID, long len )
  126. {    OSErr err; long n;
  127.  
  128.     tfu = 0;
  129.     for ( err=noErr; !err && len; )
  130.     {    n = min ( len, pagesize-(addr&pagemask) );
  131.         PrintDebug ( CatString(CatString("¥pCore->File; addr: ",NumString(addr)), CatString("¥p; bytes: ",NumString(n))),0);
  132.         err = FSWrite ( fileID, &n, RdPtr(addr) );
  133.         addr += n;
  134.         len -= n;
  135.         tfu += n;
  136.     }
  137.     return err;
  138. }
  139.  
  140.  
  141. /* -----    Read core from file -----------------------------------------------------------
  142.         stores what the z80 cpu would write
  143.         ROM is automatically protected
  144. */
  145. OSErr File2Core ( short fileID, Short addr, long len )
  146. {    OSErr err; long n;
  147.  
  148.     tfu = 0;
  149.     for ( err=noErr; !err && len; )
  150.     {    n = min ( len, pagesize-(addr&pagemask ) );
  151.         PrintDebug ( CatString(CatString("¥pFile->Core; addr: ",NumString(addr)), CatString("¥p; bytes: ",NumString(n))),0);
  152.         err = FSRead ( fileID, &n, WrPtr(addr) );
  153.         addr += n;
  154.         len -= n;
  155.         tfu += n;
  156.     }
  157.     return err;
  158. }
  159.  
  160.  
  161. /* -----    Copy core to buffer -----------------------------------------------------------
  162.         copies what the z80 cpu would read
  163. */
  164. Core2Buffer ( Short addr, void* bu, long len )
  165. {    long n;
  166.  
  167.     while ( len )
  168.     {    n = min ( len, pagesize-(addr&pagemask ) );
  169.         memcpy ( bu, RdPtr(addr), n );
  170.         bu = (Char*)bu+n;
  171.         addr += n;
  172.         len -= n;
  173.     }
  174. }
  175.  
  176. /* -----    Copy buffer to core ------------------------------------------------------------
  177.         copies what the z80 cpu would write
  178. */
  179. Buffer2Core ( void* bu, Short addr, long len )
  180. {    long n;
  181.  
  182.     while ( len )
  183.     {    n = min ( len, pagesize-(addr&pagemask ) );
  184.         memcpy ( WrPtr(addr), bu, n );
  185.         bu = (Char*)bu+n;
  186.         addr += n;
  187.         len -= n;
  188.     }
  189. }
  190.  
  191. /* -----    Copy core to core --------------------------------------------------------------
  192.         copies what the z80 cpu would copy
  193. */
  194. Core2Core ( Short src, Short dest, long len )
  195. {    long n;
  196.  
  197.     while (len)
  198.     {    n = min ( min ( len, pagesize-(src&pagemask ) ), pagesize-(dest&pagemask ) );
  199.         memcpy ( WrPtr(dest), RdPtr(src), n );
  200.         src += n;
  201.         dest += n;
  202.         len -= n;
  203.     }    
  204. }
  205.  
  206. /* -----    Copy buffer to buffer (just for completeness) ------------------------------------
  207. */
  208. Buffer2Buffer ( void* src, void* dest, long len )
  209. {
  210.     memcpy ( dest, src, len );
  211. }
  212.  
  213.  
  214. /* -----    Send byte to ZX 128's paging control port ----------------------------------------
  215.         Bits 0-2:    Ram for top 16k:    0 is the usual bank;   7 contains some scratchpads used by the 128k editor.
  216.         Bit 3:    Screen select:        0 => Use the normal screen in bank 5;    1 => Use the shadow screen in bank 7.
  217.         Bit 4:    ROM for lower 16k:    0 => 128k editor;                    1 => 48k BASIC
  218.         Bit 5:    Lock. If set, disables all further paging.
  219. */
  220. ZX128PageCtrl ( Char n )
  221. {
  222.     if (z80_hardware!=zx_128) return;            // not a ZX 128
  223.     if (zx128pagectrl&0x20) return;            // further paging disabled
  224.     zx128pagectrl = n;
  225.     rpage[0] = (n&0x10) ? rom[1] : rom[0];        // ROM select
  226.     video_page = (n&0x08) ? ram[7] : ram[5];    // video RAM select
  227.     rpage[3] = wpage[3] = ram[n&0x07]-0xc000;    // upper RAM page select
  228. }
  229.  
  230.  
  231. /* -----    Initialialize the z80 engine --------------------------------------------
  232.         allocate rom, ram, and norom pages
  233.         initialize rom[], ram[] and norom
  234.         initialize rpage[] and wpage[] for reset
  235.         CORE points to reset core which is allocated in 4 consecutive pages!
  236.         init random generator for r register handling
  237.         calculate flag tables
  238.          initialize zreg
  239.         reset z80
  240.         On a 68k machine:
  241.         ・ the core is aligned to a multiple of 0x00010000
  242.         ・ some byte behind the last byte a preset with rst0 opcodes
  243.         ・ high words of pointers in zreg struct are set to point to the core
  244. */
  245. InitZ80 ( int hardware )
  246. {    int i, roms, rams;
  247.     OSErr err=noErr;
  248.     Char *p;
  249.  
  250.     switch (hardware)
  251.     {
  252.     case zx_48k:    roms=1; rams=3; break;
  253.     case zx_128:    roms=2; rams=8; break;
  254.     default:        abort("¥pInitZ80():","¥pillegal model number: ",NumString(hardware));
  255.     }
  256.     z80_hardware = hardware;
  257.  
  258. // allocate dummy write page for ROMs
  259.     if (!norom)    norom = (Char*)NewPtr(pagesize);
  260.     if (!norom)    abort_oomem ( "¥pInitZ80()" );
  261.  
  262. // dispose of old core
  263.     if (CORE_M) DisposHandle((Handle)CORE_M);
  264.     CORE = nil; CORE_M = nil;
  265.  
  266.     for (i=maxrompages;i--;) rom[i] = nil;
  267.     for (i=maxrampages;i--;) ram[i] = nil;
  268.     for (i=4;i--;) rpage[i] = wpage[i] = norom-i*pagesize;    // fail safe pointers
  269.  
  270. /* allocate rom and ram pages:
  271.     zx_48k:    CORE+0x0000    = rom[0]    = rpage[0]
  272.             CORE+0x4000    = ram[1]    = rpage[1]
  273.             CORE+0x8000    = ram[2]    = rpage[2]
  274.             CORE+0xC000    = ram[3]     = rpage[3]
  275.     
  276.     zx_128:    CORE+0x0000    = rom[0]    = rpage[0]
  277.             CORE+0x4000    = ram[5]    = rpage[1]
  278.             CORE+0x8000    = ram[2]    = rpage[2]
  279.             CORE+0xC000    = ram[0]     = rpage[3]
  280. */
  281. #if !GENERATINGPOWERPC 
  282. //    put rom[0] and ram[1...3] resp. ram[5/2/0] in a memory block aligned to a multiple of 0x10000
  283. //    additional ram and rom is located physically before pointer CORE !!!
  284.     CORE_M = (Char**)TempNewHandle ((roms+rams)*pagesize+0x10010,&err);
  285.     if (!CORE_M||err) abort_oomem ( "¥pInitZ80()" );
  286.     HLock((Handle)CORE_M);
  287.     CORE = *CORE_M+(roms+rams)*pagesize;
  288.     CORE -= (Short)CORE;
  289.     memset ( CORE+0x10000, 199, 0x10 );         // rst 0
  290.     ABC=ADE=AHL=AIX=AIY=APC=ASP=CORE;    // setup high words of register pointers
  291. #else
  292. // simple allocation in PowerPC version
  293.     CORE_M = (Char**)TempNewHandle ((roms+rams)*pagesize,&err);
  294.     if (!CORE_M||err) abort_oomem ( "¥pInitZ80()" );
  295.     HLock((Handle)CORE_M);
  296.     CORE = *CORE_M + (roms+rams-4)*pagesize;    // to mimic 68k version
  297. #endif
  298.  
  299. // initialize rom[] and ram[]
  300.     switch (z80_hardware)
  301.     {
  302.     case zx_48k:
  303.         rom[0] = CORE;
  304.         ram[1] = CORE+0x4000;
  305.         ram[2] = CORE+0x8000;
  306.         ram[3] = CORE+0xc000;
  307.         break;
  308.     case zx_128:
  309.         rom[0] = CORE;
  310.         ram[5] = CORE+0x4000;
  311.         ram[2] = CORE+0x8000;
  312.         ram[0] = CORE+0xc000;
  313.         p=CORE;
  314.         rom[1] = p-=pagesize;
  315.         for (i=0;i<rams;i++) if (!ram[i]) ram[i] = p-=pagesize;
  316.         break;
  317.     }
  318.  
  319. // initialize rpage[], wpage[]
  320.     for (i=4;i--;)    rpage[i] = wpage[i] = CORE;
  321.     wpage[0] = norom;
  322.  
  323. // init z80 registers:
  324.     zreg.ff2 = zreg.aa2 = zreg.ff = zreg.aa = 0;    // clear high bytes of A/A2 and F/F2
  325.     BC=DE=HL=IX=IY=PC=SP=BC2=DE2=HL2=0;    // clear registers
  326.     RA=RA2=RF=RF2=RR=RI=0;
  327.     IFF1    = IFF2 = disabled;                    // disable interrupts
  328.     IM    = 1;                                // interrupt mode := 1    
  329.     WUFF= 0;                                // clear irpt, nmi
  330.     EXIT    = 0;                                // clear watchdog
  331.     IRPTCMD = 0xff;                        // byte read from bus in im0 or im2 mode
  332.  
  333. // build flag tables:
  334. // Z80:    %SZ-H-VNC    --- H & N ignored
  335. // m68:    %---XSZVC    --- X ignored
  336. // the unused flags correspond as follows:   z80{%--1H2-N-}  ==  m68{%1H2N----}       11.12.94 KIO !
  337.     for (i=0; i<256; i++)
  338.     {    
  339.     zlog_flags[i]    = (i&0x80) + ((i==0)<<6) + (  ( (~i+(i>>1)+(i>>2)+(i>>3)+(i>>4)+(i>>5)+(i>>6)+(i>>7))&1 ) << 2  );
  340. #if !GENERATINGPOWERPC
  341.     mlog_flags[i]    = ((i>=128)<<3) + ((i==0)<<2) + (  ( (~i+(i>>1)+(i>>2)+(i>>3)+(i>>4)+(i>>5)+(i>>6)+(i>>7))&1 ) << 1  );
  342.     z80flags[i]    = ((i<<4)&0xc0) + ((i<<1)&4) + (i&1)   +   ((i>>2)&0x38) + ((i>>3)&2);
  343.     m68flags[i]    = ((i>>4)&0x0c) + ((i>>1)&2) + (i&1)   +   ((i<<2)&0xe0) + ((i<<3)&0x10);
  344. #endif
  345.     };
  346.     
  347. // initialize random generator for r register
  348.     GetDateTime((unsigned long*)&qd.randSeed);
  349. }
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360.